package com.zzyl.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zzyl.exception.BaseException;
import com.zzyl.service.WechatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WechatServiceImpl implements WechatService {

    // 登录
    private static final String REQUEST_URL = "https://api.weixin.qq.com/sns/jscode2session?grant_type=client_credential";

    // 获取token
    private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

    // 获取手机号
    private static final String PHONE_REQUEST_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";

    @Value("${zzyl.wechat.appId}")
    private String appId;

    @Value("${zzyl.wechat.appSecret}")
    private String secret;

    /**
     * 获取openid
     * @param code 登录凭证
     * @return 唯一标识
     */
    @Override
    public String getOpenid(String code) {
        // 1.封装请求参数
        Map<String, Object> requestUrlParam = this.getAppConfig();
        requestUrlParam.put("js_code", code);
        // 2.发送get请求调用微信接口获取openid
        String response = HttpUtil.get(REQUEST_URL, requestUrlParam);
        // 3.解析响应结果
        JSONObject jsonObject = JSONUtil.parseObj(response);
        // 4.判断响应结果是否成功
        if (ObjectUtil.isNotEmpty(jsonObject.getInt("errcode"))) {
            // 若code不正确，则获取不到openid，响应失败
            throw new BaseException(jsonObject.getStr("errmsg"));
        }
        // 5.返回openid
        return jsonObject.getStr("openid");
    }

    /**
     * 获取接口调用凭证 access_token
     * @return access_token
     */
    public String getAccessToken() {
        // 1.封装请求参数
        Map<String, Object> requestUrlParam = this.getAppConfig();
        // 2.发送get请求调用微信接口获取token
        String response = HttpUtil.get(TOKEN_URL, requestUrlParam);
        // 3.解析响应结果
        JSONObject jsonObject = JSONUtil.parseObj(response);
        // 4.判断响应结果是否成功
        if (ObjectUtil.isNotEmpty(jsonObject.getInt("errcode"))) {
            // 若code不正确，则获取不到token，响应失败
            throw new BaseException(jsonObject.getStr("errmsg"));
        }
        // 5.返回token
        return jsonObject.getStr("access_token");
    }

    /**
     * 获取手机号
     * @param code 手机号凭证
     * @return 唯一标识
     */
    @Override
    public String getPhoneNum(String code) {
        // 1.获取服务端调用凭证 token
        String accessToken = this.getAccessToken();
        if (StrUtil.isBlank(accessToken)) {
            throw new BaseException("登录失败");
        }
        // 拼接请求路径
        String url = PHONE_REQUEST_URL + accessToken;
        // 2.封装请求参数
        Map<String, Object> requestUrlParam = new HashMap<>();
        requestUrlParam.put("code", code);
        // 3.发送post请求调用微信接口获取手机号
        String response = HttpUtil.post(url, requestUrlParam);
        // 4.解析响应结果
        JSONObject jsonObject = JSONUtil.parseObj(response);
        // 5.判断响应结果是否成功
        if (jsonObject.getInt("errcode") != 0) {
            // 若code不正确，则获取不到手机号，响应失败
            throw new BaseException(jsonObject.getStr("errmsg"));
        }
        // 6.返回手机号
        return jsonObject.getJSONObject("phone_info").getStr("phoneNumber");
    }

    /**
     * 获取应用配置
     * @return 参数集合
     */
    private Map<String, Object> getAppConfig() {
        Map<String, Object> requestUrlParam = new HashMap<>();
        // 小程序appId，开发者后台获取
        requestUrlParam.put("appid", appId);
        // 小程序secret，开发者后台获取
        requestUrlParam.put("secret", secret);
        return requestUrlParam;
    }
}
